package love.yuanmengrobot.zframe.ioc;
/*
 *   @Studio:CHJY · 源梦科技
 *   @Author:CHJY创幻
 *   @Ide:IntelliJ IDEA
 *   @Creation time:2021/7/7 16:02
 */

import love.yuanmengrobot.zframe.ioc.annotation.Autowired;
import love.yuanmengrobot.zframe.ioc.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanFactoryTest {
public static ThreadLocal threadLocal=new ThreadLocal();

    /**
     * 饿汉模式
     */
    private static BeanFactoryTest instance = new BeanFactoryTest();
    public static Map<String, Object> mapController;
    public static Map<String, Object> mapMapper;
    public static Map<String, Object> mapService;


    private static SqlSessionFactory sqlSessionFactory;
    /*
    相当于JDBC中的Connection
     */
    public static SqlSession sqlSession;


    public static void  init()  {
        try {
        InputStream in = Class.forName("love.yuanmengrobot.zframe.ioc.BeanFactoryTest").getResourceAsStream("/mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        sqlSession = sqlSessionFactory.openSession(false);

        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void forElement(List<Element> list) {//完成mapper与mybatis实例化，存储到mapMapper
        for (Element e : list) {
            String id = e.attributeValue("id");
            if ("mapper".equals(id)) {
                List<Element> childElements = e.elements();//得到ele的子元素集合
                String base_package = null;
                String controllerPackageName = null;
                for (Element childEle : childElements) {
                    base_package = childEle.attributeValue("base-package");

                    if (base_package == null || base_package.length() == 0) continue;
                    controllerPackageName = base_package;//遍历获取包名路径
                /*
                根据包名称构建要扫描的完整路径
                 */
                    String path = controllerPackageName.replace(".", "/");
                    System.out.println("path:" + path);
                    URI uri = null;
                    try {
                        if (BeanFactoryTest.class.getResource("/" + path) == null) {
                            System.out.println("出错：" + path + "--找不到文件");
                            continue;
                        }
                        ;
                        uri = BeanFactoryTest.class.getResource("/" + path).toURI();
//                        System.out.println("路径：" + uri);
                        File controllerDirectory = new File(uri);
                        String controllerFileNames[] = controllerDirectory.list();
                        for (String controllerFileName : controllerFileNames) {
                            if (!controllerFileName.endsWith(".class")) continue;
                            String clazzName = StringUtils.substringBefore(controllerFileName, ".class");
                            //全限定类名=包名 + 类名
                            String controllerClassName = controllerPackageName + "." + clazzName;
//                            System.out.println("动态：" + controllerClassName + "  类名：" + clazzName);
                            //动态加载类
                            Class<?> controllerClass = Class.forName(controllerClassName);
//                            mapMapperClass.put(controllerClassName, controllerClass);
                            mapMapper.put(controllerClassName, sqlSession.getMapper(controllerClass));
//                            System.out.println(mapMapper);
                        }
                    } catch (URISyntaxException ee) {
                        ee.printStackTrace();
                    } catch (ClassNotFoundException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

    public static void forElementService(List<Element> list) {//完成ServiceImpl实例化，存储到 mapService
        for (Element e : list) {
            String id = e.attributeValue("id");
            if ("service".equals(id)) {
                List<Element> childElements = e.elements();//得到ele的子元素集合
                String base_package = null;
                String serviceImplPackageName = null;
                for (Element childEle : childElements) {
                    base_package = childEle.attributeValue("base-package");

                    if (base_package == null || base_package.length() == 0) continue;
                    serviceImplPackageName = base_package;//遍历获取包名路径
                    String path = serviceImplPackageName.replace(".", "/");
//                    System.out.println("path:" + path);
                    URI uri = null;
                    try {
                        if (BeanFactoryTest.class.getResource("/" + path) == null) {
                            System.out.println("出错：" + path + "--找不到文件");
                            continue;
                        }
                        ;
                        uri = BeanFactoryTest.class.getResource("/" + path).toURI();
//                        System.out.println("路径：" + uri);
                        File serviceImplDirectory = new File(uri);
                        String serviceImplFileNames[] = serviceImplDirectory.list();
                        for (String serviceImplFileName : serviceImplFileNames) {
                            if (!serviceImplFileName.endsWith(".class")) continue;
                            String clazzName = StringUtils.substringBefore(serviceImplFileName, ".class");
                            //全限定类名=包名 + 类名
                            String serviceImplClassName = serviceImplPackageName + "." + clazzName;
//                            System.out.println("serviceImpl动态：" + serviceImplClassName + "  类名：" + clazzName);
                            //动态加载类
//                            Class<?> serviceImplClass = Class.forName(serviceImplClassName);
                            Object serviceImplClassIn = Class.forName(serviceImplClassName).newInstance();
                            Field[] fields = serviceImplClassIn.getClass().getDeclaredFields();
//                            System.out.println("准备查询----" + fields.length);
                            for (Field f : fields) {
                                System.out.print(f.getName() + " : ");
                                if (f.isAnnotationPresent(Resource.class)) {//查找注解了Resource的mapper声明
                                    String fname = f.getType().toString();
                                    String fpathName = fname.substring(10);
//                                    System.out.println("查询结果：" + fname + ":");
                                    if (fname.substring(0, 9).equals("interface")) {
                                        System.out.println(fpathName);
                                        if (mapMapper.containsKey(fpathName)) {
//                                            Object ob=mapMapper.get(fpathName);
                                            f.setAccessible(true);//暴力修改属性
                                            f.set(serviceImplClassIn, mapMapper.get(fpathName));//利用反射把属性注入
                                        } else {
                                            System.out.println("出错：找不到-" + fpathName);
                                        }
                                    } else {

                                    }
                                }
                            }
                            mapService.put(serviceImplClassName, serviceImplClassIn);
//                            System.out.println(mapService);
                        }
                    } catch (URISyntaxException ee) {
                        ee.printStackTrace();
                    } catch (ClassNotFoundException e1) {
                        e1.printStackTrace();
                    } catch (IllegalAccessException e1) {
                        e1.printStackTrace();
                    } catch (InstantiationException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

    //    forElementController
    public static void forElementController(List<Element> list) {//完成Controller实例化，存储到 mapController
        for (Element e : list) {
            String id = e.attributeValue("id");
            if ("controller".equals(id)) {
                List<Element> childElements = e.elements();//得到ele的子元素集合
                String base_package = null;
                String controllerPackageName = null;
                for (Element childEle : childElements) {
                    base_package = childEle.attributeValue("base-package");
                    if (base_package == null || base_package.length() == 0) continue;
                    controllerPackageName = base_package;//遍历获取包名路径
                    String path = controllerPackageName.replace(".", "/");
//                    System.out.println("path:" + path);
                    URI uri = null;
                    try {
                        if (BeanFactoryTest.class.getResource("/" + path) == null) {
                            System.out.println("出错：" + path + "--找不到文件");
                            continue;
                        }
                        ;
                        uri = BeanFactoryTest.class.getResource("/" + path).toURI();
//                        System.out.println("路径：" + uri);
                        File controllerDirectory = new File(uri);
                        String controllerFileNames[] = controllerDirectory.list();
                        for (String controllerFileName : controllerFileNames) {
                            if (!controllerFileName.endsWith(".class")) continue;
                            String clazzName = StringUtils.substringBefore(controllerFileName, ".class");
                            //全限定类名=包名 + 类名
                            String controllerClassName = controllerPackageName + "." + clazzName;
//                            System.out.println("controller动态：" + controllerClassName + "  类名：" + clazzName);
                            //动态加载类
//                            Class<?> serviceImplClass = Class.forName(serviceImplClassName);
                            Object controllerClassIn = Class.forName(controllerClassName).newInstance();
                            Field[] fields = controllerClassIn.getClass().getDeclaredFields();
//                            System.out.println("准备查询----" + fields.length);
                            for (Field f : fields) {
                                System.out.print(f.getName() + " : ");
                                if (f.isAnnotationPresent(Autowired.class)) {//查找注解了Autowired的service声明
                                    String fname = f.getType().toString();
                                    String fpathName = fname.substring(10);
//                                    System.out.println("查询结果：" + fname + ":");
                                    if (fname.substring(0, 9).equals("interface")) {
                                        System.out.println(fpathName);
                                        fpathName = fpathName + "Impl";
                                        int index = fpathName.lastIndexOf(".");
                                        StringBuilder fp = new StringBuilder(fpathName);//构造一个StringBuilder对象

                                        fp.insert(index, ".impl");
                                        fpathName = fp.toString();
//                                        System.out.println("修改结果：" + fpathName);

                                        if (mapService.containsKey(fpathName)) {
//                                            Object ob=mapMapper.get(fpathName);
                                            f.setAccessible(true);//暴力修改属性
                                            f.set(controllerClassIn, mapService.get(fpathName));//利用反射把属性注入
                                        } else {
                                            System.out.println("出错：找不到-" + fpathName);
                                        }
                                    }
                                }
                            }
                            controllerClassName = controllerClassName.substring(controllerClassName.lastIndexOf(".") + 1);
                            controllerClassName = StringUtils.replaceChars(controllerClassName, controllerClassName.substring(0, 1), controllerClassName.substring(0, 1).toLowerCase());

//                        System.out.println("最后备注："+controllerClassName);
                            mapController.put(controllerClassName, controllerClassIn);
//                            System.out.println(mapController);
                        }
                    } catch (URISyntaxException ee) {
                        ee.printStackTrace();
                    } catch (ClassNotFoundException e1) {
                        e1.printStackTrace();
                    } catch (IllegalAccessException e1) {
                        e1.printStackTrace();
                    } catch (InstantiationException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

    static List  list;

    //静态块：JVM遇到静态块会直接执行
    static  {
        try {

            System.out.println("====================》Bean工厂启动《===================");
            SAXReader reader = new SAXReader();
            InputStream in = Class.forName("love.yuanmengrobot.zframe.ioc.BeanFactoryTest")
                    .getResourceAsStream("/bean-factory.xml");
//            System.out.println(in);
            Document doc = reader.read(in);
//            System.out.println(doc);
            // xPathExpression：xPath表达式
            if (mapMapper == null)
                mapMapper = new HashMap<String, Object>();
            if (mapService == null)
                mapService = new HashMap<String, Object>();
            if (mapController == null)
                mapController = new HashMap<String, Object>();

//            System.out.println("准备初始化Bean");
            init();
//            System.out.println("初始化Bean完成");
            list = doc.selectNodes("/beans/bean");
//            System.out.println("准备list");
            forElement(list);//实例化mapper
            forElementService(list);
            forElementController(list);

            System.out.println("====================》Bean工厂完成《===================");
//            for (Element ele : list) {
//                parseElement(ele);
//            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }

    public BeanFactoryTest() {
    }

    public static BeanFactoryTest getInstance() {
        return instance;
    }

    public Object getBean(String id) {
        return mapController.get(id);
    }

}
